logo
Expand description

RustCrypto: Digital Signature Algorithms

crate Docs Build Status Apache2/MIT licensed Rust Version Project Chat

This crate contains traits which provide generic, object-safe APIs for generating and verifying digital signatures.

Used by the ecdsa and ed25519 crates, with forthcoming support in the rsa crate.

See also the Signatory crate for trait wrappers for using these traits with many popular Rust cryptography crates, including ed25519-dalek, ring, secp256k1-rs, and sodiumoxide.

Documentation

Minimum Supported Rust Version

Rust 1.56 or higher.

Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump.

SemVer Policy

  • All on-by-default features of this library are covered by SemVer
  • MSRV is considered exempt from SemVer as noted above
  • The off-by-default features derive-preview and digest-preview are unstable “preview” features which are also considered exempt from SemVer. Breaking changes to these features will, like MSRV, be done with a minor version bump.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Design

This crate provides a common set of traits for signing and verifying digital signatures intended to be implemented by libraries which produce or contain implementations of digital signature algorithms, and used by libraries which want to produce or verify digital signatures while generically supporting any compatible backend.

Goals

The traits provided by this crate were designed with the following goals in mind:

  • Provide an easy-to-use, misuse resistant API optimized for consumers (as opposed to implementers) of its traits.
  • Support common type-safe wrappers around “bag-of-bytes” representations which can be directly parsed from or written to the “wire”.
  • Expose a trait/object-safe API where signers/verifiers spanning multiple homogeneous provider implementations can be seamlessly leveraged together in the same logical “keyring” so long as they operate on the same underlying signature type.
  • Allow one provider type to potentially implement support (including being generic over) several signature types.
  • Keep signature algorithm customizations / “knobs” out-of-band from the signing/verification APIs, ideally pushing such concerns into the type system so that algorithm mismatches are caught as type errors.
  • Opaque error type which minimizes information leaked from cryptographic failures, as “rich” error types in these scenarios are often a source of sidechannel information for attackers (e.g. BB’06)

Implementation

To accomplish the above goals, the Signer and Verifier traits provided by this are generic over a Signature return value, and use generic parameters rather than associated types. Notably, they use such a parameter for the return value, allowing it to be inferred by the type checker based on the desired signature type.

The Signature trait is bounded on AsRef<[u8]>, enforcing that signature types are thin wrappers around a “bag-of-bytes” serialization. Inspiration for this approach comes from the Ed25519 signature system, which was based on the observation that past systems were not prescriptive about how signatures should be represented on-the-wire, and that lead to a proliferation of different wire formats and confusion about which ones should be used. This crate aims to provide similar simplicity by minimizing the number of steps involved to obtain a serializable signature.

Alternatives considered

This crate is based on over two years of exploration of how to encapsulate digital signature systems in the most flexible, developer-friendly way. During that time many design alternatives were explored, tradeoffs compared, and ultimately the provided API was selected.

The tradeoffs made in this API have all been to improve simplicity, ergonomics, type safety, and flexibility for consumers of the traits. At times, this has come at a cost to implementers. Below are some concerns we are cognizant of which were considered in the design of the API:

  • “Bag-of-bytes” serialization precludes signature providers from using their own internal representation of a signature, which can be helpful for many reasons (e.g. advanced signature system features like batch verification). Alternatively each provider could define its own signature type, using a marker trait to identify the particular signature algorithm, have From impls for converting to/from [u8; N], and a marker trait for identifying a specific signature algorithm.
  • Associated types, rather than generic parameters of traits, could allow more customization of the types used by a particular signature system, e.g. using custom error types.

It may still make sense to continue to explore the above tradeoffs, but with a new set of traits which are intended to be implementor-friendly, rather than consumer friendly. The existing Signer and Verifier traits could have blanket impls for the “provider-friendly” traits. However, as noted above this is a design space easily explored after stabilizing the consumer-oriented traits, and thus we consider these more important.

That said, below are some caveats of trying to design such traits, and why we haven’t actively pursued them:

  • Generics in the return position are already used to select which trait impl to use, i.e. for a particular signature algorithm/system. Avoiding a unified, concrete signature type adds another dimension to complexity and compiler errors, and in our experience makes them unsuitable for this sort of API. We believe such an API is the natural one for signature systems, reflecting the natural way they are written absent a trait.
  • Associated types preclude multiple (or generic) implementations of the same trait. These parameters are common in signature systems, notably ones which support different digest algorithms.
  • Digital signatures are almost always larger than the present 32-entry trait impl limitation on array types, which complicates trait signatures for these types (particularly things like From or Borrow bounds). This may be more interesting to explore after const generics.

Unstable features

Despite being post-1.0, this crate includes a number of off-by-default unstable features named *-preview, each of which depends on a pre-1.0 crate.

These features are considered exempt from SemVer. See the SemVer policy above for more information.

The following unstable features are presently supported:

  • derive-preview: for implementers of signature systems using DigestSigner and DigestVerifier, the derive-preview feature can be used to derive Signer and Verifier traits which prehash the input message using the PrehashSignature::Digest algorithm for a given Signature type. When the derive-preview feature is enabled import the proc macros with use signature::{Signer, Verifier} and then add a derive(Signer) or derive(Verifier) attribute to the given digest signer/verifier type. Enabling this feature also enables digest support (see immediately below).
  • digest-preview: enables the DigestSigner and DigestVerifier traits which are based on the Digest trait from the digest crate. These traits are used for representing signature systems based on the Fiat-Shamir heuristic which compute a random challenge value to sign by computing a cryptographically secure digest of the input message.
  • rand-preview: enables the RandomizedSigner trait for signature systems which rely on a cryptographically secure random number generator for security.

NOTE: the async-signature crate contains experimental async support for Signer and DigestSigner.

Re-exports

pub use digest;
pub use rand_core;

Modules

hazmathazmat-preview
Hazardous Materials: low-level APIs which can be insecure if misused.

Structs

Signature errors.

Traits

DigestSignerdigest-preview
Sign the given prehashed message Digest using Self.
DigestVerifierdigest-preview
Verify the provided signature for the given prehashed message Digest is authentic.
Signing keypair with an associated verifying key.
PrehashSignaturedigest-preview
Marker trait for Signature types computable as 𝐒(𝐇(𝒎)) i.e. ones which prehash a message to be signed as 𝐇(𝒎)
RandomizedDigestSignerdigest-preview and rand-preview
Combination of DigestSigner and RandomizedSigner with support for computing a signature over a digest which requires entropy from an RNG.
RandomizedSignerrand-preview
Sign the given message using the provided external randomness source.
Trait impl’d by concrete types that represent digital signatures.
Sign the provided message bytestring using Self (e.g. a cryptographic key or connection to an HSM), returning a digital signature.
Sign the provided message bytestring using &mut Self (e.g., an evolving cryptographic key), returning a digital signature.
Verify the provided message bytestring using Self (e.g. a public key)

Type Definitions

Result type.

Derive Macros

DigestSignerderive-preview and digest-preview
Derive the DigestSigner trait for a type which impls PrehashSigner.
DigestVerifierderive-preview and digest-preview
Derive the DigestVerifier trait for a type which impls PrehashVerifier.
Signerderive-preview
Derive the Signer trait for a type which impls DigestSigner.
Verifierderive-preview
Derive the Verifier trait for a type which impls DigestVerifier.